<template>
  <WidgetContainer :data="data" context-menu>
    <q-card class="q-pa-sm column full-height">
      <div class="widget-header text-h6 ellipsis relative-position">
        <q-btn flat dense icon="checklist"></q-btn>
        <span>任务计划</span>
        <div class="absolute-right">
          <q-icon class="cursor-pointer widget-header__append-icon"
                  name="smart_toy"
                  @click="messageRobotUpdate">
            <q-tooltip content-class="bg-primary" :offset="[10, 10]">配置机器人</q-tooltip>
          </q-icon>
          <q-icon :color="showLoop===true?'green':''" class="cursor-pointer widget-header__append-icon"
                  name="repeat"
                  @click="switchMode('showLoop')">
            <q-tooltip content-class="bg-primary" :offset="[10, 10]">显示重复任务</q-tooltip>
          </q-icon>
          <q-icon :color="showCompleted===true?'green':''" class="cursor-pointer widget-header__append-icon"
                  name="check_circle_outline"
                  @click="switchMode('showCompleted')">
            <q-tooltip content-class="bg-primary" :offset="[10, 10]">显示已完成任务</q-tooltip>
          </q-icon>
          <q-icon :color="showTodo===true?'green':''" class="cursor-pointer widget-header__append-icon"
                  name="radio_button_unchecked"
                  @click="switchMode('showTodo')">
            <q-tooltip content-class="bg-primary" :offset="[10, 10]">显示未完成任务（Todo）</q-tooltip>
          </q-icon>
        </div>
      </div>
      <div class="col scroll hide-scrollbar full-width" @contextmenu.stop.prevent>
        <template v-if="showSkeleton">
          <q-list>
            <q-item style="max-width: 300px" v-for="(e,index) in Array(12)" :key="index+!!e">
              <q-item-section avatar>
                <q-skeleton type="QAvatar"/>
              </q-item-section>
              <q-item-section>
                <q-item-label>
                  <q-skeleton type="text"/>
                </q-item-label>
                <q-item-label caption>
                  <q-skeleton type="text" width="65%"/>
                </q-item-label>
              </q-item-section>
            </q-item>
          </q-list>
        </template>
        <template v-else>
          <transition-group name="list" tag="div">
            <template v-for="task in tasks">
              <q-card v-if="task.mode === 'show'" :key="task.id"
                      @click="task.mode = 'edit'"
                      class="task-card q-mb-sm cursor-pointer" flat bordered>
                <q-card-section>
                  <div class="row">
                    <q-checkbox v-model="task.checked" @input="onFinishTask(task)"/>
                    <div>
                      <div class="q-mt-sm q-mb-xs">{{ task.name }}</div>
                      <div class="task-alarm">
                        <!--暂时隐藏未完成的 Group 功能-->
                        <div class="inline-block" v-if="task.groupName">
                          <span v-if="task.groupName" style="font-size: 0.9em;color: dimgray;">{{
                              task.groupName
                            }}</span>
                        </div>
                        <div class="inline-block" v-if="task.alertDate">
                          <q-icon round name="event"></q-icon>
                          <span style="font-size: 0.9em;color: indianred">{{
                              $filters.dateFormat(task.alertDate)
                            }}</span>
                        </div>
                        <div class="inline-block" v-if="task.alertTime">
                          <q-icon round name="alarm"></q-icon>
                          <span style="font-size: 0.9em;color: indianred">在 {{ $filters.timeFormat(task.alertTime) }} 提醒我</span>
                        </div>
                        <div class="inline-block" v-if="task.repeatRule">
                          <q-icon round name="repeat"></q-icon>
                          <span class="text-caption"
                                v-if="task.repeatRule"
                                style="color: indianred">
                            <span v-if="task.repeatRule === 'daily'">每天</span>
                            <span v-if="task.repeatRule === 'workday'">工作日</span>
                            <span v-if="task.repeatRule === 'weekly'">每周</span>
                            <span v-if="task.repeatRule === 'monthly'">每月</span>
                            <span v-if="task.repeatRule === 'yearly'">每年</span>
                            <span v-if="typeof task.repeatRule === 'object'">自定义</span>
                          </span>
                        </div>
                      </div>
                    </div>
                  </div>
                  <q-popup-proxy v-model="task.showPopup" context-menu>
                    <q-list style="min-width: 100px">
                      <q-item clickable v-close-popup @click.stop="editTask(task)">
                        <q-item-section>编辑任务</q-item-section>
                      </q-item>
                      <q-separator/>
                      <q-item clickable v-close-popup @click.stop="deleteTask(task)">
                        <q-item-section>删除任务</q-item-section>
                      </q-item>
                    </q-list>
                  </q-popup-proxy>
                </q-card-section>
              </q-card>
              <q-card v-else :key="task.id"
                      class="q-mb-sm cursor-pointer" flat bordered>
                <q-card-section>
                  <div class="row">
                    <div class="task-input-icon-prepend">
                      <q-icon v-if="task.name" class="task-input-prepend-icon"
                              name="check_box_outline_blank"></q-icon>
                      <q-icon v-if="!task.name" class="task-input-prepend-icon" name="add"></q-icon>
                    </div>
                    <q-input dense stack-label class="col"
                             v-model="task.name"
                             label="点击输入新待办"
                             maxlength="32"
                             ref="input"
                             @blur="onBlur(task)"
                             @keydown.enter="task.mode ==='create'? createTask(task) : updateTask(task)">
                      <template v-slot:append>
                        <q-icon v-if="task.name" name="event"
                                class="cursor-pointer q-ml-sm">
                          <q-popup-proxy>
                            <q-date v-model="task.alertDate"
                                    first-day-of-week="1"
                                    mask="YYYY-MM-DD HH:mm" color="purple"/>
                          </q-popup-proxy>
                        </q-icon>
                        <span class="text-caption"
                              v-if="task.alertDate"
                              style="color: indianred">
                          {{ $filters.dateFormat(task.alertDate) }}
                        </span>
                        <q-icon v-if="task.name" name="alarm" class="cursor-pointer">
                          <q-popup-proxy>
                            <q-time v-model="task.alertTime"
                                    mask="YYYY-MM-DD HH:mm" color="purple"/>
                          </q-popup-proxy>
                        </q-icon>
                        <span class="text-caption"
                              v-if="task.alertTime"
                              style="color: indianred">在 {{ $filters.timeFormat(task.alertTime) }} 提醒我
                        </span>
                        <q-icon v-if="task.name" name="repeat" class="cursor-pointer">
                          <q-popup-proxy>
                            <q-list style="min-width: 100px">
                              <q-item clickable v-close-popup @click.stop="updateRepeatRule(task,'daily')">
                                <q-item-section>每天</q-item-section>
                              </q-item>
                              <q-separator/>
                              <q-item clickable v-close-popup @click.stop="updateRepeatRule(task,'workday')">
                                <q-item-section>工作日</q-item-section>
                              </q-item>
                              <q-separator/>
                              <q-item clickable v-close-popup @click.stop="updateRepeatRule(task,'weekly')">
                                <q-item-section>每周</q-item-section>
                              </q-item>
                              <q-separator/>
                              <q-item clickable v-close-popup @click.stop="updateRepeatRule(task,'monthly')">
                                <q-item-section>每月</q-item-section>
                              </q-item>
                              <q-separator/>
                              <q-item clickable v-close-popup @click.stop="updateRepeatRule(task,'yearly')">
                                <q-item-section>每年</q-item-section>
                              </q-item>
                              <q-separator/>
                              <q-item clickable v-close-popup @click.stop="updateRepeatRule(task,'custom')">
                                <q-item-section>自定义</q-item-section>
                              </q-item>
                              <q-separator/>
                              <q-item clickable v-close-popup @click.stop="updateRepeatRule(task,'none')">
                                <q-item-section class="text-negative">禁用重复</q-item-section>
                              </q-item>
                            </q-list>
                          </q-popup-proxy>
                        </q-icon>
                        <span class="text-caption"
                              v-if="task.repeatRule"
                              style="color: indianred">
                          <span v-if="task.repeatRule === 'daily'">每天</span>
                          <span v-if="task.repeatRule === 'workday'">工作日</span>
                          <span v-if="task.repeatRule === 'weekly'">每周</span>
                          <span v-if="task.repeatRule === 'monthly'">每月</span>
                          <span v-if="task.repeatRule === 'yearly'">每年</span>
                          <span v-if="typeof task.repeatRule === 'object'">自定义</span>
                        </span>
                      </template>
                    </q-input>
                  </div>
                </q-card-section>
              </q-card>
            </template>
          </transition-group>
        </template>
      </div>
    </q-card>
    <RepeatRuleEditForm v-model:show="repeatDialogVisible"
                        v-model="repeatDialogData"
                        @submit="submitRepeatRule"
    ></RepeatRuleEditForm>
    <MessageRobotEditForm v-model:show="messageRobotDialogVisible"
                          v-model="todo.notifyConfig.channels"
                          @submit="submitRobot"
    ></MessageRobotEditForm>
  </WidgetContainer>
</template>

<script>
import WidgetContainer from '../components/WidgetContainer'
import RepeatRuleEditForm from './management/RepeatRuleEditForm'
import widget from '../../../mixins/widget'
import { genWidgetId } from '../../../utils/widget'
import MessageRobotEditForm from './management/MessageRobotEditForm'
import iUser from '../../../api/user'
import dayjs from 'dayjs'

export default {
  name: 'TaskPanelWidget',
  mixins: [widget],
  components: {
    WidgetContainer,
    RepeatRuleEditForm,
    MessageRobotEditForm
  },
  props: {
    data: Object
  },
  data () {
    return {
      showSkeleton: true,
      showTodo: true,
      showCompleted: false,
      showLoop: false,
      messageRobotDialogVisible: false,
      repeatDialogVisible: false,
      repeatDialogData: null,
      todo: {
        tasks: [],
        groups: [],
        notifyConfig: {
          browser: true,
          channels: []
        }
      },
      uncheckedTask: [],
      checkedTask: [],
      repeatTask: [],
      remindTimer: null,
      newTask: {
        ...this.getTaskTemplate(),
        showPopup: false,
        mode: 'create',
        id: 'NEW_TASK'
      },
      tasks: [],
      editingTask: null,
      robots: []
    }
  },
  created () {
    const widgetData = this.formData.data
    this.todo = widgetData || {
      tasks: [
        {
          id: 1,
          name: '去麦当劳大吃一顿 🍔🍦',
          memo: '吃一堆好吃的，可以考虑订外卖',
          alertDate: new Date('2020/7/21'),
          alertTime: new Date('2020/7/21'),
          endTime: new Date(),
          repeatRule: null,
          createdAt: new Date(),
          checked: false,
          groupName: '日常生活'
        },
        {
          id: 2,
          name: '去海底捞吃火锅 🥘🍻',
          memo: '火锅不错呦~ 啦啦啦啦啦',
          alertDate: new Date('2020/7/21'),
          alertTime: new Date('2020/7/21'),
          endTime: new Date(),
          repeatRule: null,
          createdAt: new Date(),
          checked: false,
          groupName: '日常生活'
        }
      ],
      group: [],
      notifyConfig: {
        browser: true,
        channels: []
      }
    }
    if (!this.todo.notifyConfig) {
      this.todo.notifyConfig = {
        browser: true,
        channels: []
      }
    }
    this.todo.tasks = this.todo.tasks.map(e => {
      e.showPopup = false
      e.mode = 'show'
      return e
    })
  },
  inject: ['workbenchEventBus'],
  computed: {
    currentTask () {
      if (this.showLoop) {
        return this.repeatTask
      }
      return [
        ...(this.showCompleted ? this.checkedTask : []),
        ...(this.showTodo ? this.uncheckedTask : [])
      ]
    }
  },
  watch: {
    currentTask () {
      this.tasks = [
        ...this.currentTask,
        ...(this.showTodo ? [this.newTask] : [])
      ]
    }
  },
  async mounted () {
    this.workbenchEventBus.on('keydown', this.onWorkbenchKeydown)
    setTimeout(() => {
      this.filterTask()
      this.showSkeleton = false
      // 任务提醒机制
      if (!this.remindTimer) {
        this.remindTimer = setInterval(() => {
          this.todo.tasks.forEach(task => {
            if (!task.alertTime) return
            const timeGap = +new Date() - +new Date(task.alertTime)
            if (timeGap < 500 && timeGap >= -500) {
              this.$q.notify({
                icon: 'insert_emoticon',
                message: task.name,
                color: 'green',
                position: 'top',
                timeout: 5000
              })
              // eslint-disable-next-line no-new
              new Notification('任务计划提醒 ⏰', {
                body: `${task.name}`,
                icon: 'https://workbench-1301845716.cos.ap-nanjing.myqcloud.com/icon_db6242de75e9f780c0846525ecd6af08.png'
              })
            }
          })
        }, 1000)
      }
    }, 800)
    await this.initRobots()
  },
  beforeUnmount () {
    this.workbenchEventBus.off('keydown', this.onWorkbenchKeydown)
  },
  methods: {
    async initRobots () {
      if (!this.$store.getters.isLogin) return
      const robots = await iUser.findAllMsgRobot({
        query: {
          group: this.data.id
        }
      })
      this.robots = robots.map(e => {
        return {
          name: e.message,
          rule: e.rule
        }
      })
    },
    switchMode (mode) {
      this.showCompleted = false
      this.showLoop = false
      this.showTodo = false
      this[mode] = true
    },
    messageRobotUpdate () {
      this.messageRobotDialogVisible = true
    },
    onWorkbenchKeydown (event) {
      if (event.code === 'KeyD') {
        event.preventDefault()
        this.$refs.input.focus()
      }
    },
    saveTaskPanelWidget () {
      this.formData.data = {
        tasks: this.todo.tasks.map(e => {
          delete e.showPopup
          delete e.showEdit
          return e
        }),
        group: this.todo.group,
        notifyConfig: this.todo.notifyConfig
      }
      this.saveWidget()
    },
    filterTask (delay) {
      setTimeout(() => {
        this.uncheckedTask = this.todo.tasks.filter(e => !e.checked)
        this.checkedTask = this.todo.tasks.filter(e => e.checked)
        this.repeatTask = this.todo.tasks.filter(e => e.repeatRule)
      }, delay || 300)
    },
    getTaskTemplate () {
      return {
        name: '',
        memo: '',
        alertDate: null,
        alertTime: null,
        endTime: null,
        repeatRule: null,
        createdAt: new Date(),
        checked: false,
        groupName: null
      }
    },
    async createTask (task) {
      const createdTask = {
        ...this.getTaskTemplate(),
        ...task,
        id: genWidgetId('TASK'),
        mode: 'show'
      }
      const robot = await this.registryRobot(createdTask)
      createdTask.robot = robot || null
      this.todo.tasks.push(createdTask)
      Object.assign(this.newTask, this.getTaskTemplate())
      this.filterTask(1)
      this.saveTaskPanelWidget()
    },
    async updateTask (task) {
      task.mode = 'show'
      task.showPopup = false
      const robot = await this.registryRobot(task)
      task.robot = robot || null
      this.saveTaskPanelWidget()
    },
    async syncTaskRobots () {
      for (const task of this.tasks) {
        await this.registryRobot(task)
      }
    },
    async registryRobot (task) {
      if (!task.repeatRule) return
      const alertTime = task.alertTime ? dayjs(task.alertTime) : null
      const alertDate = task.alertDate ? dayjs(task.alertDate) : null
      let rule = {
        second: null,
        minute: null,
        hour: null,
        date: null,
        month: null,
        year: null,
        dayOfWeek: []
      }
      const time = alertTime
          ? {
            second: alertTime.get('second'),
            minute: alertTime.get('minute'),
            hour: alertTime.get('hour')
          }
          : {
            second: null,
            minute: null,
            hour: null
          }
      const date = alertDate
          ? {
            dayOfWeek: alertDate.day(),
            date: alertDate.get('date'),
            month: alertDate.get('month'),
            year: alertDate.get('year')
          }
          : {
            dayOfWeek: null,
            date: null,
            month: null,
            year: null
          }
      if (task.repeatRule === 'daily') {
        rule = { ...rule, ...time }
      }
      if (task.repeatRule === 'workday') {
        rule = {
          ...rule,
          ...time,
          dayOfWeek: [1, 2, 3, 4, 5]
        }
      }
      if (task.repeatRule === 'weekly') {
        rule = {
          ...rule,
          ...time,
          dayOfWeek: date.dayOfWeek
        }
      }
      if (task.repeatRule === 'monthly') {
        rule = {
          ...rule,
          ...time,
          date: date.date
        }
      }
      if (task.repeatRule === 'yearly') {
        rule = {
          ...rule,
          ...time,
          date: date.date,
          month: date.month
        }
      }
      if (typeof task.repeatRule === 'object') {
        rule = task.repeatRule.rule
      }
      let robotId = task.robot
      const channels = this.todo.notifyConfig.channels
      if (robotId) {
        await iUser.updateMsgRobot({
          id: robotId,
          update: {
            rule: rule,
            group: this.data.id,
            message: task.name,
            channels: channels
          }
        })
      } else if (channels && channels.length > 0) {
        robotId = await iUser.createMsgRobot({
          rule: rule,
          group: this.data.id,
          message: task.name,
          channels: channels
        })
      }
      return robotId
    },
    onFinishTask () {
      this.filterTask()
      this.saveTaskPanelWidget()
    },
    editTask (task) {
      task.mode = 'edit'
    },
    async deleteTask (task) {
      if (task.robot) {
        await iUser.deleteMsgRobot({ id: task.robot })
      }
      this.todo.tasks = this.todo.tasks.filter(e => e.id !== task.id)
      this.filterTask(1)
      this.saveTaskPanelWidget()
    },
    onBlur (task) {
      if (task.mode === 'edit') {
        this.updateTask(task)
      }
    },
    updateRepeatRule (task, ruleType) {
      if (ruleType === 'custom') {
        this.repeatDialogVisible = true
        this.editingTask = task
        if (typeof task.repeatRule === 'object') {
          this.repeatDialogData = task.repeatRule
        }
        return
      }
      if (ruleType === 'none') {
        task.repeatRule = null
        this.saveTaskPanelWidget()
        return
      }
      if (!task.alertDate && ~['weekly', 'monthly', 'yearly'].indexOf(ruleType)) {
        task.alertDate = dayjs().startOf('day').hour(8).toDate()
      }
      if (!task.alertTime && ~['daily', 'workday'].indexOf(ruleType)) {
        task.alertTime = dayjs().startOf('day').hour(8).toDate()
      }
      task.repeatRule = ruleType
      this.saveTaskPanelWidget()
    },
    async submitRobot () {
      await this.saveTaskPanelWidget()
      await this.syncTaskRobots()
    },
    async submitRepeatRule () {
      if (!this.editingTask) return
      this.editingTask.repeatRule = this.repeatDialogData
      await this.saveTaskPanelWidget()
      await this.syncTaskRobots()
    }
  }
}
</script>

<style lang="scss">
.task-card {
  &:hover {
    background-color: rgba(245, 245, 245, 0.46);
  }
}

.task-input-icon-prepend {
  display: inline-block;
  width: 40px;
  height: 40px;

  .task-input-prepend-icon {
    top: 25%;
    left: 25%;
    width: 50%;
    height: 50%;
    line-height: 40px;
    font-size: 28px;
    color: rgba(52, 130, 71, 0.54);
  }
}

.task-alarm {
  div:not(:first-child):before {
    content: '▪';
    margin: 0 4px;
  }
}

.list-enter-active {
  transition: all .5s;
}

.list-leave-active {
  transition: all .5s;
}

.list-enter {
  opacity: 0;
  transform: translateY(30px);
}

.list-leave-to {
  opacity: 0;
  transform: translateX(-300px);
}

.list-move {
  transition: transform .5s;
}
</style>
